/**
 * 智能问题分析系统
 * 实现了基于关键词和多因素的问题优先级评估、时间衰减和位置聚集度分析、问题相似度匹配功能
 * 支持生成问题热力图数据
 */

// 问题接口定义
export interface Question {
  id: string;
  facilityId: string;
  facilityName: string;
  date: string;
  reporter_name: string;
  type: string;
  description: string;
  status: string;
  priority: string;
  adminReply?: string;
  location?: {
    x: number;
    y: number;
  };
}

// 热力图数据点接口
export interface HeatmapPoint {
  x: number;
  y: number;
  value: number;
}

// 关键词权重配置
const KEYWORDS_WEIGHTS: Record<string, number> = {
  '紧急': 5,
  '危险': 5,
  '安全隐患': 4,
  '漏水': 3,
  '损坏': 3,
  '故障': 3,
  '不工作': 2,
  '问题': 1,
  '建议': 0.5
};

// 问题类型权重配置
const ISSUE_TYPE_WEIGHTS: Record<string, number> = {
  '安全隐患': 5,
  '设施损坏': 3,
  '卫生问题': 2,
  '其他': 1
};

// 优先级权重配置
const PRIORITY_WEIGHTS: Record<string, number> = {
  '高': 3,
  '中': 2,
  '低': 1
};

/**
 * 计算问题的关键词权重分数
 * @param question 问题对象
 * @returns 关键词权重分数
 */
export function calculateKeywordScore(question: Question): number {
  let score = 0;
  const description = question.description.toLowerCase();

  // 检查描述中是否包含关键词
  Object.entries(KEYWORDS_WEIGHTS).forEach(([keyword, weight]) => {
    if (description.includes(keyword.toLowerCase())) {
      score += weight;
    }
  });

  // 添加问题类型权重
  score += ISSUE_TYPE_WEIGHTS[question.type] || 1;

  // 添加优先级权重
  score += PRIORITY_WEIGHTS[question.priority] || 1;

  return score;
}

/**
 * 计算时间衰减因子
 * 问题越新，权重越高
 * @param dateString 日期字符串 (YYYY-MM-DD)
 * @returns 时间衰减因子 (0-1)
 */
export function calculateTimeDecayFactor(dateString: string): number {
  const reportDate = new Date(dateString);
  const currentDate = new Date();

  // 计算天数差
  const diffTime = Math.abs(currentDate.getTime() - reportDate.getTime());
  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

  // 使用指数衰减函数: e^(-λt)，其中λ是衰减率，t是时间
  // 这里使用λ=0.05，30天后权重降至约0.22
  return Math.exp(-0.05 * diffDays);
}

/**
 * 计算位置聚集度
 * 返回在指定半径内的问题数量
 * @param questions 所有问题列表
 * @param targetQuestion 目标问题
 * @param radiusMeters 半径（米）
 * @returns 聚集度分数
 */
export function calculateLocationClusterScore(
  questions: Question[],
  targetQuestion: Question,
  radiusMeters: number = 100
): number {
  if (!targetQuestion.location) return 0;

  // 计算在指定半径内的问题数量
  const nearbyQuestions = questions.filter(q => {
    if (!q.location || q.id === targetQuestion.id) return false;

    // 使用简化的距离计算（平面距离）
    const dx = q.location.x - targetQuestion.location!.x;
    const dy = q.location.y - targetQuestion.location!.y;
    const distanceSquared = dx * dx + dy * dy;

    // 这里使用平方距离比较，避免开方运算
    // 实际应用中应根据坐标系统进行适当的距离计算
    return distanceSquared <= (radiusMeters * radiusMeters);
  });

  return nearbyQuestions.length;
}

/**
 * 计算问题相似度
 * 使用简单的词汇重叠方法
 * @param question1 问题1
 * @param question2 问题2
 * @returns 相似度分数 (0-1)
 */
export function calculateSimilarity(question1: Question, question2: Question): number {
  // 如果问题类型不同，相似度降低
  const typeMatch = question1.type === question2.type ? 0.3 : 0;

  // 分词并计算重叠度
  const words1 = question1.description.toLowerCase().split(/\s+/);
  const words2 = question2.description.toLowerCase().split(/\s+/);

  const uniqueWords1 = new Set(words1);
  const uniqueWords2 = new Set(words2);

  let commonWords = 0;
  uniqueWords1.forEach(word => {
    if (uniqueWords2.has(word)) commonWords++;
  });

  // 计算Jaccard相似度
  const totalUniqueWords = new Set([...uniqueWords1, ...uniqueWords2]).size;
  const jaccardSimilarity = totalUniqueWords > 0 ? commonWords / totalUniqueWords : 0;

  return typeMatch + (0.7 * jaccardSimilarity);
}

/**
 * 计算问题的综合权重分数
 * @param question 问题对象
 * @param allQuestions 所有问题列表
 * @returns 综合权重分数
 */
export function calculateQuestionWeight(question: Question, allQuestions: Question[]): number {
  // 基础分数：关键词权重
  const keywordScore = calculateKeywordScore(question);

  // 时间因子：新问题权重更高
  const timeFactor = calculateTimeDecayFactor(question.date);

  // 位置聚集度：问题密集区域权重更高
  const clusterScore = calculateLocationClusterScore(allQuestions, question);

  // 已处理问题权重降低
  const statusFactor = question.status === '已处理' ? 0.3 : 1;

  // 综合计算最终权重
  return keywordScore * timeFactor * (1 + clusterScore * 0.1) * statusFactor;
}

/**
 * 生成问题热力图数据
 * @param questions 问题列表
 * @returns 热力图数据点数组
 */
export function generateHeatmapData(questions: Question[]): HeatmapPoint[] {
  // 过滤掉没有位置信息的问题
  const questionsWithLocation = questions.filter(q => q.location);

  // 计算每个问题的权重
  return questionsWithLocation.map(question => {
    const weight = calculateQuestionWeight(question, questions);

    return {
      x: question.location!.x,
      y: question.location!.y,
      value: weight
    };
  });
}

/**
 * 查找相似问题
 * @param targetQuestion 目标问题
 * @param questions 问题库
 * @param threshold 相似度阈值 (0-1)
 * @returns 相似问题数组
 */
export function findSimilarQuestions(
  targetQuestion: Question,
  questions: Question[],
  threshold: number = 0.6
): Question[] {
  return questions
    .filter(q => q.id !== targetQuestion.id)
    .map(q => ({
      question: q,
      similarity: calculateSimilarity(targetQuestion, q)
    }))
    .filter(item => item.similarity >= threshold)
    .sort((a, b) => b.similarity - a.similarity)
    .map(item => item.question);
}
